package frame

import (
	"fmt"
	"sync"

	"gitee.com/go-mao/mao/libs/config"
	"gitee.com/go-mao/mao/libs/try"
	"gopkg.in/ini.v1"
)

type MaoConfigInterface interface {
	Core() *ini.File
	Get(c ConfigInterface) ConfigInterface
	GetByAlias(alias string) ConfigInterface
	Save(confPtr ConfigInterface)
}

type configDomain struct {
	RunMode string
	sync.Mutex
	*ini.File
	server     *Server
	configsMap map[string]ConfigInterface
	indexList  []string
}

// 初始化配置
func (this *configDomain) loadConfig(file any) {
	var err error
	this.File, err = ini.Load(file)
	if err != nil {
		try.Throw(CODE_FATAL, "配置读取失败", err.Error())
		return
	}
	this.RunMode = this.Section("server").Key("mode").String()
}

// 初始化配置
func (this *configDomain) init(module ModuleInterface) {
	if this.configsMap == nil {
		this.configsMap = make(map[string]ConfigInterface)
	}
	components := module.Components()
	for _, component := range components {
		configer, ok := component.(Configer)
		if !ok {
			continue
		}
		conf := configer.Config()
		var alias = conf.ConfigAlias()
		if _, ok := this.configsMap[alias]; ok {
			try.Throwf(CODE_FATAL, "配置%s重复", conf.ConfigName())
			return
		}
		this.Read(conf)
		this.configsMap[alias] = conf
		this.indexList = append(this.indexList, alias)
		this.Save(conf) //更新配置
	}
}

// 获取配置,如果配置不存在则返回默认配置
// 该方法返回一个副本，避免外部修改了配置
func (this *configDomain) Read(c ConfigInterface) ConfigInterface {
	this.Lock()
	defer this.Unlock()
	alias := c.ConfigAlias()
	conf, ok := this.configsMap[alias]
	if !ok {
		conf = c.Default()
		filename := this.getConfigFile(alias)
		config.Read(filename, conf)
		this.configsMap[alias] = conf
	}
	return conf
}

// 根据别名获取配置
func (this *configDomain) GetByAlias(alias string) ConfigInterface {
	this.Lock()
	defer this.Unlock()
	conf, ok := this.configsMap[alias]
	if !ok {
		try.Throwf(CODE_WARN, "配置%s获取失败", alias)
	}
	conf.BeforeGet()
	return conf
}

// 根据别名获取配置
func (this *configDomain) Get(c ConfigInterface) ConfigInterface {
	this.Lock()
	defer this.Unlock()
	conf, ok := this.configsMap[c.ConfigAlias()]
	if ok {
		c = conf
	}
	c.BeforeGet()
	return c
}

// 保存配置
func (this *configDomain) Save(confPtr ConfigInterface) {
	this.Lock()
	defer this.Unlock()
	alias := confPtr.ConfigAlias()
	filename := this.getConfigFile(alias)
	if err := config.Write(filename, confPtr); err != nil {
		try.Throwf(CODE_ERROR, "配置%s保存失败：%s", confPtr.ConfigName(), err.Error())
	}
	this.configsMap[alias] = confPtr
}

// 根据别名获取配置文件名
func (this *configDomain) getConfigFile(alias string) string {
	return fmt.Sprintf("%s/%s.json", DIR_CONFIG, alias)
}

// 核心配置
func (this *configDomain) Core() *ini.File {
	return this.File
}
